//////////////////////////////////////////////////////////////////////////
//
// Globant Cpp Training 1
//
// Types and Declarations
//
//////////////////////////////////////////////////////////////////////////

#include <iostream>

//////////////////////////////////////////////////////////////////////////
// Question: Which of the following implementations of the reset function 
// is best for initializing the array to all zero?
/*
struct foo {
    foo() { reset(); }
    void reset() {
        // A // memset(x, 0, 50);
        // B // memset(x, 0, sizeof(x));
        // C // memset(x, 0, 50 * 4);
        // D // memset(x, 0, 50 * sizeof(x));
    }

    long x[50];
};

int main() {

}*/
// Answer: B
// Description: B is the only answer that is portable. 
// C will work on platforms where long is 4 bytes, but many platforms have 8 byte long.
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Question: What is the value of the local variable x at the end of main?
/*
int x = 5;
int main() {
    const int x = x;
}*/
// Answer: Undefined
// Description: The local x in main hides the global x before the local x's 
// initializer is considered. Therefore the local x is being initialized 
// with itself (the local uninitialized variable)
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: What is the value of y at the end of main?
/*
const int x = 5;
int main(int argc, char** argv) {
    int x[x];
    const int y = sizeof(x) / sizeof(int);
    std::cout << "Value = " << y << std::endl;
}*/
// Answer: 5
// Description: The local x does not hide the global x until the end of 
// the declaration. A local name will hide a global after the end of 
// the declaration but before the beginning of initialization.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: Given the code below, the variable y can be accessed in 
// which blocks of code?
/*
int main(int argc, char** argv) {
    if (argc > 10) {

    } else if (int y = argc - 1) {

    } else {

    }
}*/
// Answer: else if and else
// Description: The variable declared in the else-if did not exist 
// before its declaration and cannot be used after the end of the 
// else clause. Variables declared in conditions of if, else-if, else 
// structures can be used in all subsequent conditions and bodies of the 
// if, else-if, else structure.
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Question: What value for y gets printed in the program below?

/*
const int x = 12;

int main(int argc, char** argv) {
    enum {
        x = x,
        y
    };
    std::cout << y << std::endl;
}*/
// Answer: 13
// Description: An Enumeration's point of declaration is after its 
// definition (which includes the initialization). 
// Therefore in this case the value of the enum 'x' is initialized 
// with the global 'x' which equals 12.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: What value is printed out for the variable x?
/*
int x;

int main() {
    int y;
    std::cout << x << std::endl;
    std::cout << y << std::endl;
} */
// Answer: 0
// Description: Variables with static storage duration are zero initialized. 
// Note that x has static storage duration even though the static 
// keyword is not used. According to the standard: 
// "All objects which do not have dynamic storage duration, 
// do not have thread storage duration, and are not local 
// have static storage duration"
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: The code below declares and defines variable x?
/*
extern int x;
int main() {}*/
// Answer: False
// Description: An extern declaration does not define the variable unless 
// it is also initialized in the same statement.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: Which of the following lines should NOT compile?
/*
int main() {
    int a[54] = {};
    int b[54] = {};
    int* x = a;
    int* const y = a;
    b = x;
    b = y;
} */
// Answer: 5, 6
// Description: Arrays can be implicitly converted to pointers without casting. 
// There is no implicit conversion from pointers to arrays.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: Which of the following lines should NOT compile?
/*
int main() {
    int a = 2;
    int* b = &a;
    int const* c = b;
    b = c;
} */
// Answer: 4
// Description: int* can be implicity converted to int const*. 
// There is no implicit conversion from int const* to int*.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: Will "Hello World" be printed by the program below?
/*
struct Foo
{
    int x;
    int y;
};

int main(int argc, char** argv)
{
    Foo f;

    if (&f.x < &f.y) {
        std::cout << "Hello World" << std::endl;
    }
}*/
// Answer: Yes
// Description: Relational operators can be used to do pointer comparison 
// of non-static members in the same object where the definitions of the 
// members is not separated by an access specifier. The member declared 
// first will evaluate to lower.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: The code below would declare an array of references, 
// if we had properly initialized the references. True or false?
/*
int main() 
{ 
    int& x[50];
} */
// Answer: False
// Description: There is no such thing as an array of references. 
// Also there are no references to references or pointers to references.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: What value gets printed by the program?
/*
int foo(int x, int y)
{
    return x + y;
}

double foo(double x, double y)
{
    return x + y;
}

int main(int argc, char** argv)
{
    double (*ptr)(int, int);

    ptr = foo;

    std::cout << ptr(3,8) << std::endl;
}*/
// Answer: Ill-formed
// Description: The return type of a function does not alter the signature 
// (for function overloading). However, the return type of a function DOES 
// change the "type" of the function and thus the assignment of foo to ptr in not valid.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: Which, if any, of the member function definitions below are ill-formed?
/*
int g_x = 44; 

struct Foo 
{ 
    int m_x; 

    static int s_x; 

    Foo(int x) : m_x(x) {} 

    int a(int x = g_x) 
    { 
        return x + 1; 
    } 

    int b(int x = m_x) 
    { 
        return x + 1; 
    } 

    int c(int x = s_x) 
    { 
        return x + 1; 
    } 
}; 

int Foo::s_x = 22; 

int main(int argc, char** argv) 
{ 
    Foo f(6); 

    std::cout << f.a() << std::endl; 
    std::cout << f.b() << std::endl; 
    std::cout << f.c() << std::endl; 
}*/
// Answer: b
// Description: b is ill-formed. Non-static members can not be used as default arguments.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: What is the output of the program?
/*
struct A 
{ 
    virtual int foo(int x = 5) { 
        return x * 2; 
    } 
}; 

struct B : public A 
{ 
    int foo(int x = 10) { 
        return x * 3; 
    } 
}; 

int main() {
    A* a = new B; 
    std::cout << a->foo() << std::endl; 
}*/
// Answer: 15
// Description: The method B::foo is called but with the default argument 
// of 5 from A::foo. "A virtual function call uses the default arguments 
// in the declaration of the virtual function determined by the static type 
// of the pointer or reference denoting the object. An overriding function 
// in a derived class does not acquire default arguments from the function it overrides."
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: What is the output of the program?
/*
struct BS
{
    unsigned int color;
};

struct car : public BS
{
};

struct truck : public BS
{
};

struct city : public car, public truck
{
};

int main(int argc, char** argv) 
{ 
    city c;
    c.color = 3;
    std::cout << c.color << std::endl;
}*/
// Answer: ill-formed
// Description: The code is ill-formed. The non-static members of a base class, 
// that is an indirect or direct base class more than once, 
// can not be referred to without qualification.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: How many times is Hello World printed by this program?
/*
struct Base {
    Base() { std::cout << "Hello World" << std::endl; }
    unsigned int color;
};

struct Derived1 : virtual public Base { };
struct Derived2 : virtual public Base { };
struct Derived3 : public Base { };
struct Derived4 : public Base { };

struct Derived : public Derived1, 
                 public Derived2, 
                 public Derived3, 
                 public Derived4 { };

int main() { 
    Derived derived; 
}*/
// Answer: 3
// Description: One time for the first virtual occurrences of BS in the 
// hierarchy and once for each non-virtual occurrence of BS. Derived1 and Derived2 
// together have one. Derived3 and Derived4 each have one.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: What gets printed by this program?
/*
struct Shape {
    virtual void print() { std::cout << "SHAPE" << std::endl; }
    virtual ~Shape() {}
};
struct Box : public virtual Shape
{
    void print() { std::cout << "BOX" << std::endl; }
};
struct Sphere : public virtual Shape
{
    void print() { std::cout << "SPHERE" << std::endl; }
};
struct GeoDisc : public Box, public Sphere { };
int main() {
    Shape* shape = new GeoDisc;
    shape->print();
    delete shape;
}*/
// Answer: ill-formed
// Description: Virtual functions must have a unique "final overrider" that 
// overrides all other instances of that function in its inheritance heirarchy. 
// In this case neither Box::print nor Sphere::print override each other, 
// so the condition is not met and the GeoDisc class is ill-formed.
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Question: How many times is Hello World printed by this program?
/*
struct Base {
    Base() { std::cout << "Hello World" << std::endl; }
};
struct Derived1 : public Base { };
struct Derived2 : public Base { };
struct Derived3 : public Base { };
struct Derived4 : public Base { };
struct Derived : public virtual Derived1, public virtual Derived2, 
                 public virtual Derived3, public Derived4 { };

int main() { 
    Derived derived;
}*/
// Answer: 4
// Description: Virtual inheritance affects the class that is inherited virtually. 
// Therefore the BS base class is not inherited virtually and there are 4 of 
// them within 1 DR object. The virtual inheritance statements in this code are 
// affecting the classes mid1, mid2, mid3, mid4 and not BS.
//////////////////////////////////////////////////////////////////////////

void f(int argument)
{
    // Do some stuff
}

int main() {
    void (*pf) (const int r) = f;
}
